/*
 * Copyright © OpenAtom Foundation.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package io.iec.edp.caf.generator.utils;

import lombok.extern.slf4j.Slf4j;

import javax.tools.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author liu_wei
 */
@Slf4j
public class CompilerUtils {
    private static JavaCompiler javaCompiler;
    private static String encoding = "UTF-8";

    private CompilerUtils() {
    }

    ;

    private static JavaCompiler getJavaCompiler() {
        if (javaCompiler == null) {
            synchronized (CompilerUtils.class) {
                if (javaCompiler == null) {
                    javaCompiler = ToolProvider.getSystemJavaCompiler();
                }
            }
        }
        return javaCompiler;
    }


    /**
     * @param encoding  编译编码
     * @param jarPaths 需要加载的jar的路径
     * @param filePath  文件或者目录（若为目录，自动递归编译）
     * @param sourceDir java源文件存放目录
     * @param targetDir 编译后class类文件存放目录
     * @author zhouyjtr
     */
    public static void compiler(String filePath, String targetDir, String sourceDir, String encoding, ArrayList<String> jarPaths)
            throws Exception {

        //得到filePath目录下的所有java源文件
        List<File> sourceFileList = File4ComplierUtils.getSourceFiles(filePath);

        if (sourceFileList.size() == 0) {
            // 没有java文件，直接返回
            log.warn(filePath + "目录下查找不到任何java文件");
            return;
        }
        // 获取所有jar
        StringBuilder jars = new StringBuilder("");
        for (String jarPath :
                jarPaths) {
            jars.append(jarPath);
        }

        File targetFile = new File(targetDir);
        if (!targetFile.exists())
        {
            targetFile.mkdirs();
        }
        // 建立DiagnosticCollector对象
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        // 该文件管理器实例的作用就是将我们需要动态编译的java源文件转换为getTask需要的编译单元
        StandardJavaFileManager fileManager = getJavaCompiler().getStandardFileManager(diagnostics, null, null);
        // 获取要编译的编译单元
        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
        Iterable<String> options = Arrays.asList("-encoding", encoding, "-classpath", jars.toString(), "-d", targetDir,
                "-sourcepath", sourceDir);
        JavaCompiler.CompilationTask task = getJavaCompiler().getTask(null, fileManager, diagnostics, options, null,
                compilationUnits);
        // 运行编译任务
        // 编译源程式
        boolean success = task.call();
        StringBuilder stringBuilder = new StringBuilder();
        for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
            String line = String.format(
                    "Code: %s%n Kind: %s%n Position: %s%n Start Position: %s%n End Position: %s%n Source: %s%n Message: %s%n",
                    diagnostic.getCode(), diagnostic.getKind(), diagnostic.getPosition(), diagnostic.getStartPosition(),
                    diagnostic.getEndPosition(), diagnostic.getSource(), diagnostic.getMessage(null));
            stringBuilder.append(line);
        }
        fileManager.close();
        if (success) {
            log.info("编译成功");
        } else {
            log.error("编译失败: " + stringBuilder.toString());
        }
    }
}
